package com.fnd.med.utils;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;

public class JsonUtil {
	@SuppressWarnings("unchecked")
	public static <T> T convert(JSONObject src, Class<T> clazz) {
		T obj;
		try {
			obj = clazz.newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		Method[] methods = clazz.getMethods();
		label397: for (Method method : methods) {
			String methodName = method.getName();
			if (methodName.startsWith("set")) {
				String propertyName = getPropertyName(methodName);
				Class<?> c = method.getParameterTypes()[0];
				if (c == String.class) {
					methodInvoke(method, obj, getString(src, propertyName));
				} else if (Integer.TYPE == c) {
					methodInvoke(method, obj, Integer.valueOf(getInt(src, propertyName)));
				} else if (Long.TYPE == c) {
					methodInvoke(method, obj, Long.valueOf(getLong(src, propertyName)));
				} else if (Double.TYPE == c) {
					methodInvoke(method, obj, Double.valueOf(getDouble(src, propertyName)));
				} else if (Boolean.TYPE == c) {
					methodInvoke(method, obj, Boolean.valueOf(getBlooean(src, propertyName)));
				} else if (java.util.Date.class == c) {
					System.out.println(getString(src, propertyName));
					methodInvoke(method, obj, MeapsUtil.dateFormat(getString(src, propertyName)));
				} else if (c.equals(List.class)) {
					Object o;
					Iterator<?> localIterator;
					Class<?> cc = getParameterClass(method.getGenericParameterTypes()[0]);
					@SuppressWarnings("rawtypes")
					List list = new ArrayList();
					JSONArray array = src.getJSONArray(propertyName);
					if ((cc == String.class) || (Integer.TYPE == cc) || (Long.TYPE == cc) || (Double.TYPE == cc))
						for (localIterator = array.iterator(); localIterator.hasNext();) {
							o = localIterator.next();
							list.add(o);
						}
					else
						for (localIterator = array.iterator(); localIterator.hasNext();) {
							o = localIterator.next();
							JSONObject jsonObject = (JSONObject) o;
							if (jsonObject == null)
								break label397;
							list.add(convert(jsonObject, cc));
						}

					methodInvoke(method, obj, list);
				} else {
					JSONObject jsonObject = (JSONObject) getObj(src, propertyName);
					if (jsonObject != null)
						methodInvoke(method, obj, convert(jsonObject, c));
				}
			}
		}

		return obj;
	}

	public static <T> List<T> convert(JSONArray jsonArray, Class<T> clazz) {
		List<T> list = new ArrayList<T>();
		for (int i = 0; i < jsonArray.size(); ++i) {
			JSONObject obj = (JSONObject) jsonArray.get(i);
			list.add(convert(obj, clazz));
		}
		return list;
	}

	private static boolean getBlooean(JSONObject src, String propertyName) {
		return src.getBoolean(propertyName);
	}

	@SuppressWarnings("unused")
	private static JSONArray getJsonArray(JSONObject src, String propertyName) {
		if (!(src.containsKey(propertyName)))
			return null;

		try {
			return src.getJSONArray(propertyName);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return null;
	}

	private static Object getObj(JSONObject src, String propertyName) {
		if (!(src.containsKey(propertyName)))
			return null;
		try {
			return src.get(propertyName);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return null;
	}

	private static int getInt(JSONObject src, String propertyName) {
		if (!(src.containsKey(propertyName)))
			return 0;
		try {
			return src.getInt(propertyName);
		} catch (JSONException e) {
		}
		return 0;
	}

	private static double getDouble(JSONObject src, String propertyName) {
		if (!(src.containsKey(propertyName)))
			return 0.0D;
		try {
			return src.getDouble(propertyName);
		} catch (JSONException e) {
		}
		return 0.0D;
	}

	private static long getLong(JSONObject src, String propertyName) {
		if (!(src.containsKey(propertyName)))
			return 0L;
		try {
			return src.getLong(propertyName);
		} catch (JSONException e) {
		}
		return 0L;
	}

	private static String getString(JSONObject src, String propertyName) {
		if (!(src.containsKey(propertyName)))
			return null;
		try {
			return src.getString(propertyName);
		} catch (JSONException e) {
		}
		return null;
	}

	public static <T> void methodInvoke(Method method, T obj, Object parameter) {
		try {
			method.invoke(obj, new Object[] { parameter });
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private static String getPropertyName(String methodName) {
		return firstCharLower(methodName.substring(3));
	}

	public static java.util.Date dateConvert(String dateString, String formate) {
		java.util.Date d = null;
		SimpleDateFormat sdf = new SimpleDateFormat(formate);
		try {
			d = sdf.parse(dateString);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
		return d;
	}

	public static String dateConvert(java.util.Date date, String formate) {
		if (date == null)
			return null;
		SimpleDateFormat sdf = new SimpleDateFormat(formate);
		sdf.format(date);
		return sdf.format(date);
	}

	public static String firstCharLower(String str) {
		char[] chars = str.toCharArray();
		if ((chars[0] > '@') && (chars[0] < '['))
			chars[0] = (char) (chars[0] + ' ');

		return new String(chars);
	}

	public static String firstCharUper(String str) {
		char[] chars = str.toCharArray();
		if ((chars[0] > '`') && (chars[0] < '{'))
			chars[0] = (char) (chars[0] - ' ');

		return new String(chars);
	}

	public static Class<?> getParameterClass(Type type) {
		if (type instanceof ParameterizedType) {
			ParameterizedType p = (ParameterizedType) type;
			return ((Class<?>) p.getActualTypeArguments()[0]);
		}
		return null;
	}
}